package xyz.fivefaith.faithtool.redis;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

import xyz.fivefaith.faithtool.redis.constant.RedisConstant;

import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.Map;
import java.util.Properties;

/**
 * redis工具类
 *
 * @author zhaoanchi
 * @version 1.0
 * @since 1.0
 */
@SuppressWarnings("unchecked")
public final class RedisMapUtil {
    private static final RedissonClient CLIENT;

    /* ---------- 静态块：加载 redis.properties ---------- */
    static {
        Properties props = new Properties();
        try (InputStream in =
                RedisMapUtil.class
                        .getClassLoader()
                        .getResourceAsStream(RedisConstant.REDIS_CONFIG_PATH)) {
            if (in == null) {
                throw new RuntimeException("redis.properties not found in classpath");
            }
            props.load(in);
        } catch (IOException e) {
            throw new RuntimeException("load redis.properties error", e);
        }

        String host = props.getProperty("redis.host", "127.0.0.1");
        int port = Integer.parseInt(props.getProperty("redis.port", "6379"));
        String password = props.getProperty("redis.password");
        int db = Integer.parseInt(props.getProperty("redis.database", "0"));

        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + host + ":" + port).setDatabase(db);
        if (password != null && !password.isBlank()) {
            config.useSingleServer().setPassword(password);
        }

        CLIENT = Redisson.create(config);
    }

    /* ---------- 工具方法 ---------- */

    /** 检查值是否存在 */
    public boolean isExist(String key) {
        return CLIENT.getBucket(key).isExists();
    }

    /* ================= 普通 RMap ================= */

    /** 获取 RMap 实例 */
    public <K, V> RMap<K, V> getMap(String name) {
        return CLIENT.getMap(name);
    }

    /** 放入 KV */
    public <K, V> void put(String mapName, K key, V value) {
        getMap(mapName).put(key, value);
    }

    /** 放入 KV 并设置过期时间（整个 Map） */
    public <K, V> void putAndExpire(String mapName, K key, V value, Duration duration) {
        RMap<K, V> map = getMap(mapName);
        map.put(key, value);
        map.expire(duration);
    }

    /** 批量放入 */
    public <K, V> void putAll(String mapName, Map<K, V> m) {
        getMap(mapName).putAll(m);
    }

    /** 取值 */
    public <K, V> V get(String mapName, K key) {
        RMap<K, V> map = getMap(mapName);
        return map.get(key);
    }

    /** 删除指定 key */
    public <K, V> V removeMap(String mapName, K key) {
        RMap<K, V> map = getMap(mapName);
        return map.remove(key);
    }

    /** 批量删除 */
    public <K> void fastRemove(String mapName, K... keys) {
        getMap(mapName).fastRemove(keys);
    }

    /** 判断 key 是否存在 */
    public <K> boolean containsKey(String mapName, K key) {
        return getMap(mapName).containsKey(key);
    }

    /** Map 大小 */
    public long sizeMap(String mapName) {
        return getMap(mapName).size();
    }

    /** 清空 Map */
    public void clearMap(String mapName) {
        getMap(mapName).clear();
    }

    /* ================= 分布式锁（按 key 加锁） ================= */

    /** 对某个 key 加锁 */
    public <K> RLock getLock(String mapName, K key) {
        return getMap(mapName).getLock(key);
    }

    /* ---------- 其余工具方法保持不变 ---------- */
    public static void shutdown() {
        CLIENT.shutdown();
    }
}
